/**
  ******************************************************************************
  * @file    main.c
  * @author  ashuai0110
  * @version V2.0
  * @date    2024-09-09
  * @brief   使用举例-MODBUS从机程序
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "bsp.h"

#include "modbus_slave.h"

/* 私有宏定义-----------------------------------------------------------------*/

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/
/* modbus错误信息 */
const static char *modbusErrorStr[] = {
    "request message length error!",
    "request message check error!",
    "request message frame error!",
};

static uint8_t modbusBuf[MB_BUF_SIZE_MAX]; /* modbus所需缓存区 */
static mb_slave_t testMBS; /* modbus从机实例 */

/* 全局变量-------------------------------------------------------------------*/
uint8_t coilStatus[8] = {0xC3, 0x3C, 0x55, 0xAA};           /* 线圈 共8*8=64个 地址0~63 */
uint8_t inputStatus[8] = {0x55, 0xAA, 0xC3, 0x3C};          /* 输入线圈 共8*8=64个 地址0~63 */
uint16_t holdingRegister[8] = {0x111, 0x222, 0x333, 0x444}; /* 保持寄存器 共8*1=8个 地址0~7 */
uint16_t inputRegister[8] = {0x555, 0x666, 0x777, 0x888};   /* 输入寄存器 共8*1=8个 地址0~7 */

/* 私有函数原型---------------------------------------------------------------*/


/**
  * @brief  This function handles SysTick Handler.
  *
  * @param  None
  *
  * @retval None
  */
void SysTick_Handler(void)
{
    /* 组件计时节拍接口 */
    mw_tick_inc(1);
}

/**
  * @brief  串口中断函数
  *
  * @param  None
  *
  * @retval None
  */
void USART1_IRQHandler(void)
{
    static uint8_t rxData, txData, ret;
    
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        rxData = USART_ReceiveData(USART1);
        /* 写入接收缓存 */
        ret = mb_slave_write_rx_buf(&testMBS, &rxData, 1);
        if(1 != ret)
        {
            MW_WARN_LOG("mb_slave_write_rx_buf failure");
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
    
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {
        /* 读出发送缓存 */
        ret = mb_slave_read_tx_buf(&testMBS, &txData, 1);
        if(1 == ret)
        {
            USART_SendData(USART1, txData);
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_TXE);
    }
}

/**
  * @brief  main
  */
int main(int argc, char *argv[])
{
    MW_VER_LOG("example-modbus_slave", 2, 0, 0);
    
    /* BSP初始化 */
    bsp_init();
    
    /* modbus从机初始化 从机地址0x1 协议RTU 帧间隔超时100ms */
    mb_slave_init(&testMBS, 0x1, MB_RTU, modbusBuf, sizeof(modbusBuf), bsp_usart1_tx_en, 100);
    
    while(1)
    {
        uint8_t ret;
        /* modbus从机轮询处理 */
        ret = mb_slave_poll(&testMBS);
        /* 处理中 */
        if(MW_RET_ING == ret)
        {
        } /* 请求处理完成 */
        else if(MW_RET_OK == ret)
        {
            MW_DEBUG_LOG("request success");
        } /* 请求错误 */
        else
        {
            MW_ERROR_LOG("request error: %s", modbusErrorStr[ret - MW_RET_LEN_ERR]);
        }
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_01h(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    int16_t numTmp;
    
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(64 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(63 < reg) { return MB_ERRNO_ADDR; }
        
        numTmp = num;
        while(0 < numTmp)
        {
            /* 获取线圈状态 */
            *pData++ = mb_get_bits(&coilStatus[0], reg, numTmp > 8 ? 8 : numTmp);
            numTmp -= 8;
            reg += 8;
        }
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_02h(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    int16_t numTmp;
    
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(64 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(63 < reg) { return MB_ERRNO_ADDR; }
        
        numTmp = num;
        while(0 < numTmp)
        {
            /* 获取线圈状态 */
            *pData++ = mb_get_bits(&inputStatus[0], reg, numTmp > 8 ? 8 : numTmp);
            numTmp -= 8;
            reg += 8;
        }
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_03h(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(8 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(7 < reg) { return MB_ERRNO_ADDR; }
        
        for(uint8_t cnt = 0; cnt < num; cnt++)
        {
            /* 获取寄存器值 */
            *pData++ = holdingRegister[reg + cnt] >> 8;
            *pData++ = holdingRegister[reg + cnt] & 0xFF;
        }
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_04h(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(8 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(7 < reg) { return MB_ERRNO_ADDR; }
        
        for(uint8_t cnt = 0; cnt < num; cnt++)
        {
            /* 获取寄存器值 */
            *pData++ = inputRegister[reg + cnt] >> 8;
            *pData++ = inputRegister[reg + cnt] & 0xFF;
        }
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_05h(mb_slave_t *_mbs, uint16_t reg, uint8_t bit)
{
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 地址检查 */
        if(63 < reg) { return MB_ERRNO_ADDR; }
        /* 写入线圈状态 */
        mb_set_bits(&coilStatus[0], reg, 1, bit);
        
        MW_DEBUG_LOG("05-coilStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", coilStatus[0], coilStatus[1], \
            coilStatus[2], coilStatus[3], coilStatus[4], coilStatus[5], coilStatus[6], coilStatus[7]);
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_06h(mb_slave_t *_mbs, uint16_t reg, uint16_t data)
{
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 地址检查 */
        if(7 < reg) { return MB_ERRNO_ADDR; }
        /* 写入寄存器值 */
        holdingRegister[reg] = data;
        
        MW_DEBUG_LOG("06-holdingRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", holdingRegister[0], holdingRegister[1], \
            holdingRegister[2], holdingRegister[3], holdingRegister[4], holdingRegister[5], holdingRegister[6], holdingRegister[7]);
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_0fh(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    int16_t numTmp;
    
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(64 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(63 < reg) { return MB_ERRNO_ADDR; }
        
        MW_DEBUG_LOG("before-coilStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", coilStatus[0], coilStatus[1], \
            coilStatus[2], coilStatus[3], coilStatus[4], coilStatus[5], coilStatus[6], coilStatus[7]);
        
        numTmp = num;
        while(0 < numTmp)
        {
            /* 写入线圈状态 */
            mb_set_bits(&coilStatus[0], reg, numTmp > 8 ? 8 : numTmp, *pData++);
            numTmp -= 8;
            reg += 8;
        }
        
        MW_DEBUG_LOG("after-coilStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", coilStatus[0], coilStatus[1], \
            coilStatus[2], coilStatus[3], coilStatus[4], coilStatus[5], coilStatus[6], coilStatus[7]);
    }
    
    return MB_ERRNO_OK;
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
uint8_t mb_slave_req_10h(mb_slave_t *_mbs, uint16_t reg, uint16_t num, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbs == &testMBS)
    {
        /* 数量检查 */
        if(8 < num) { return MB_ERRNO_DATA; }
        /* 地址检查 */
        if(7 < reg) { return MB_ERRNO_ADDR; }
        
        MW_DEBUG_LOG("before-holdingRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", holdingRegister[0], holdingRegister[1], \
            holdingRegister[2], holdingRegister[3], holdingRegister[4], holdingRegister[5], holdingRegister[6], holdingRegister[7]);
        
        for(uint8_t cnt = 0; cnt < num; cnt++)
        {
            /* 写入寄存器值 */
            holdingRegister[reg + cnt] = (pData[cnt * 2] << 8) | pData[cnt * 2 + 1];
        }
        
        MW_DEBUG_LOG("after-holdingRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", holdingRegister[0], holdingRegister[1], \
            holdingRegister[2], holdingRegister[3], holdingRegister[4], holdingRegister[5], holdingRegister[6], holdingRegister[7]);
    }
    
    return MB_ERRNO_OK;
}
